﻿using System;
using System.Windows.Forms;
using Nuwanda.Common;
using Nuwanda.TfsSpotlight.Data;
using Nuwanda.TfsSpotlight.Shell;
using StructureMap;

namespace Nuwanda.TfsSpotlight.Views.Query
{
    [Author("Bartłomiej Legiędź")]
    [Pluggable("QueryView")]
    public partial class QueryView : BaseUserControl, IQueryView
    {
        private IQueryPresenter _presenter;
        private readonly ControlInvoker _invoker;

        public QueryView()
        {
            InitializeComponent();
            this.kscSplitter.SplitterDistance = 200;
            this._invoker = new ControlInvoker(this);
        }

        public void AttachPresenter(IQueryPresenter presenter)
        {
            this._presenter = presenter;
        }

        public void ClearResults()
        {
            this._invoker.RunInControlsThread(
                () => this.bsQueryResult.DataSource = null);
        }

        public void EnableResultGrid()
        {
            this._invoker.RunInControlsThread(
                () => this.gridQueryResult.Enabled = true);
        }

        public void DisableResultGrid()
        {
            this._invoker.RunInControlsThread(
                () => this.gridQueryResult.Enabled = false);
        }

        public void StartResultGridProgress()
        {
            this._invoker.RunInControlsThread(
                () => this.pbQueryProgress.Visible = true);
        }

        public void StopResultGridProgress()
        {
            this._invoker.RunInControlsThread(
                () => this.pbQueryProgress.Visible = false);
        }

        private void HandleSelectedWorkItemChanged(object sender, EventArgs e)
        {
            if (this._suspendSelectionChanged) return;

            this._presenter.HandleSelectedWorkItemChanged();
        }

        public int GetSelectedWorkItemIndex()
        {
            if (this.gridQueryResult.SelectedRows.Count == 0)
                return -1;

            return this.gridQueryResult.SelectedRows[0].Index;
        }

        public void DisplayResult(QueryResult result)
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (result == null) return;

                        this.gridQueryResult.SelectionChanged -= this.HandleSelectedWorkItemChanged;
                        this.gridQueryResult.ResultOptions = result.Options;
                        this.gridQueryResult.WorkItemCollection = result.Result;

                        var titleColumn = this.gridQueryResult.Columns["Title"];

                        if (titleColumn != null)
                        {
                            titleColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                        }

                        this.gridQueryResult.SelectionChanged += this.HandleSelectedWorkItemChanged;
                    });
        }

        public void SetQueryCaption(string caption, string countCaption)
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        this.khHeader.Values.Heading = caption;
                        this.khHeader.Values.Description = countCaption;
                    });
        }

        public void ShowDetails()
        {
            this._invoker.RunInControlsThread(
                () => this.kscSplitter.Panel2Collapsed = false);
        }

        public void HideDetails()
        {
            this._invoker.RunInControlsThread(
                () => this.kscSplitter.Panel2Collapsed = true);
        }

        public void SelectNextWorkItem()
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (!CanMoveToNextWorkItem) return;

                        var selectedRowIndex = this.gridQueryResult.SelectedRows[0].Index;

                        if (selectedRowIndex + 1 < this.gridQueryResult.Rows.Count)
                        {
                            this.gridQueryResult.Rows[selectedRowIndex + 1].Selected = true;
                        }
                    });
        }

        public bool CanMoveToNextWorkItem
        {
            get
            {
                return this._invoker.RunAndReturnInControlsThread(
                    () => this.gridQueryResult.SelectedRows.Count > 0 && this.gridQueryResult.SelectedRows[0].Index + 1 < this.gridQueryResult.Rows.Count);
                
            }
        }

        public void SelectPrevoiusWorkItem()
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (!CanMoveToPreviousWorkItem) return;

                        int selectedRowIndex = this.gridQueryResult.SelectedRows[0].Index;
                        if (selectedRowIndex - 1 >= 0)
                        {
                            this.gridQueryResult.Rows[selectedRowIndex - 1].Selected = true;
                        }
                    });
        }

        public bool CanMoveToPreviousWorkItem
        {
            get
            {
                return this._invoker.RunAndReturnInControlsThread(
                    () => this.gridQueryResult.SelectedRows.Count > 0 && this.gridQueryResult.SelectedRows[0].Index > 0);
            }
        }

        public void UpdateResultGridRows()
        {
            this._invoker.RunInControlsThread(
                () => this.gridQueryResult.RefreshGrid(true, false, false));
        }

        public void RemoveSelectionFromResultGrid()
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        foreach (DataGridViewRow row in this.gridQueryResult.SelectedRows)
                        {
                            row.Selected = false;
                        }
                    });
        }

        public void EnsureSelectedRowVisible()
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (this.gridQueryResult.SelectedRows.Count == 0) return;

                        try
                        {
                            this.gridQueryResult.FirstDisplayedScrollingRowIndex =
                                this.gridQueryResult.SelectedRows[0].Index;
                        }
                        catch (InvalidOperationException)
                        {
                        }
                    });
        }

        public QueryLayoutState GetLayoutState()
        {
            return this._invoker.RunAndReturnInControlsThread(
                () => new QueryLayoutState(true, this.kscSplitter.SplitterDistance));
            
        }

        public void ApplayLayoutState(QueryLayoutState layoutState)
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (layoutState == null) return;

                        this.kscSplitter.SplitterDistance = layoutState.QueryResultHeight;
                    });
        }

        private bool _suspendSelectionChanged;
        public void SelectFirstQueryResult()
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        if (gridQueryResult.RowCount <= 0) return;

                        this._suspendSelectionChanged = true;
                        this.gridQueryResult.ClearSelection();
                        this._suspendSelectionChanged = false;
                        this.gridQueryResult.FirstDisplayedScrollingRowIndex = 0;
                        this.gridQueryResult.Rows[0].Selected = true;
                    });
        }

        private void HandleGridDoubleClick(object sender, MouseEventArgs e)
        {
            this._presenter.HandleWorkItemDoubleClicked();
        }

        public void FillDetailsForm(Control content)
        {
            this._invoker.RunInControlsThread(
                delegate
                    {
                        content.Dock = DockStyle.Fill;
                        this.kscSplitter.Panel2.Controls.Add(content);
                    });
        }
    }
}